(function( window, $, undefined ) {
	
	/*
	* smartresize: debounced resize event for jQuery
	*
	* latest version and complete README available on Github:
	* https://github.com/louisremi/jquery.smartresize.js
	*
	* Copyright 2011 @louis_remi
	* Licensed under the MIT license.
	*/

	var $event = $.event, resizeTimeout;

	$event.special.smartresize 	= {
		setup: function() {
			$(this).bind( "resize", $event.special.smartresize.handler );
		},
		teardown: function() {
			$(this).unbind( "resize", $event.special.smartresize.handler );
		},
		handler: function( event, execAsap ) {
			// Save the context
			var context = this,
		    	args 	= arguments;
			// set correct event type
			event.type = "smartresize";
			if ( resizeTimeout ) { clearTimeout( resizeTimeout ); }
			resizeTimeout = setTimeout(function() {
				jQuery.event.handle.apply( context, args );
			}, execAsap === "execAsap"? 0 : 100 );
		}
	};

	$.fn.smartresize = function( fn ) {
		return fn ? this.bind( "smartresize", fn ) : this.trigger( "smartresize", ["execAsap"] );
	};
	
	$.Slideshow  = function( options, element ) {
		this.$el = $( element );
		/***** images ****/
		// list of image items
		this.$list	= this.$el.find('ul.ei-slider-large');
		// image items
		this.$imgItems	= this.$list.children('li');
		// total number of items
		this.itemsCount = this.$imgItems.length;
		// images
		this.$images = this.$imgItems.find('img:first');
		/***** thumbs ****/
		// thumbs wrapper
		this.$sliderthumbs	 = this.$el.find('ul.ei-slider-thumbs').hide();
		// slider elements
		this.$sliderElems	= this.$sliderthumbs.children('li');
		// sliding div
		this.$sliderElem	= this.$sliderthumbs.children('li.ei-slider-element');
		// thumbs
		this.$thumbs = this.$sliderElems.not('.ei-slider-element');
		// initialize slideshow
		this._init( options );
	};
	
	$.Slideshow.defaults = {
		// animation types:
		// "sides" : new slides will slide in from left / right
		// "center": new slides will appear in the center
		animation : 'sides', // sides || center
		// if true the slider will automatically slide, and it will only stop if the user clicks on a thumb
		autoplay : true,
		// interval for the slideshow
		slideshow_interval : 3000,
		// speed for the sliding animation
		speed : 1000,
		// easing for the sliding animation
		easing : '',
		// percentage of speed for the titles animation. Speed will be speed * titlesFactor
		titlesFactor : 0.6,
		// titles animation speed
		titlespeed	: 800,
		// titles animation easing
		titleeasing : '',
		// maximum width for the thumbs in pixels
		thumbMaxWidth : 150
    };
	
	$.Slideshow.prototype 		= {
		_init : function( options ) {
			this.options 		= $.extend( true, {}, $.Slideshow.defaults, options );
			// set the opacity of the title elements and the image items
			this.$imgItems.css( 'opacity', 0 );
			this.$imgItems.find('div.ei-title > *').css( 'opacity', 0 );
			// index of current visible slider
			this.current = 0;
			var _self = this;
			
			// preload images
			// add loading status
			this.$loading = $('<div class="ei-slider-loading">Loading</div>').prependTo( _self.$el );

			$.when( this._preloadImages() ).done( function() {
				// hide loading status
				_self.$loading.hide();
				// calculate size and position for each image
				_self._setImagesSize();
				// configure thumbs container
				_self._initThumbs();
				// show first
				_self.$imgItems.eq( _self.current ).css({
					'opacity' 	: 1,
					'z-index'	: 10
				}).show().find('div.ei-title > *').css( 'opacity', 1 );
				// if autoplay is true
				if( _self.options.autoplay ) {
					_self._startSlideshow();
				}
				// initialize the events
				_self._initEvents();
			})
		},
		_preloadImages : function() {
			// preloads all the large images
			var _self	= this,
				loaded	= 0;

            //如果一个失败了的话 就重新加载....  这里的循环加载机制太慢了
            return $.Deferred(
				function(dfd) {
					_self.$images.each( function( i ) {
                        //这里要所有图片都加载成功后才能算成功
						$('<img/>').load( function() {
							if( ++loaded === _self.itemsCount ) {
								dfd.resolve();
							}
						}).attr( 'src', $(this).attr('src') );
					});
				}
			).promise();

		},
		_setImagesSize		: function() {
			// save ei-slider's width
			this.elWidth	= this.$el.width();
			var _self	= this;
			this.$images.each( function( i ) {
				
				var $img	= $(this),
					imgDim	= _self._getImageDim( $img.attr('src') );

				$img.css({
					width		: imgDim.width,
					height		: imgDim.height,
					marginLeft	: imgDim.left,
					marginTop	: imgDim.top
				});
				
			});
		
		},
		_getImageDim : function( src ) {
			var $img   = new Image();
			$img.src   = src;

			var c_w		= this.elWidth,
				c_h		= this.$el.height(),
				r_w		= c_h / c_w,
				
				i_w		= $img.width,
				i_h		= $img.height,
				r_i		= i_h / i_w,
				new_w, new_h, new_left, new_top;

			if( r_w > r_i ) {
				new_h	= c_h;
				new_w	= c_h / r_i;
			}else {
				new_h	= c_w * r_i;
				new_w	= c_w;
			}

			return {
				width	: new_w,
				height	: new_h,
				left	: ( c_w - new_w ) / 2,
				top		: ( c_h - new_h ) / 2
			};
		
		},
		_initThumbs			: function() {
			// set the max-width of the slider elements to the one set in the plugin's options
			// also, the width of each slider element will be 100% / total number of elements
            /*
            this.$sliderElems.css({
				'max-width' : this.options.thumbMaxWidth + 'px',
				'width'		: 100 / this.itemsCount + '%'
			});*/
			
			// set the max-width of the slider and show it
			this.$sliderthumbs.show();

		},
		_startSlideshow		: function() {
		
			var _self	= this;
			
			this.slideshow	= setTimeout( function() {
				
				var pos;
				
				( _self.current === _self.itemsCount - 1 ) ? pos = 0 : pos = _self.current + 1;
				
				_self._slideTo( pos );
				
				if( _self.options.autoplay ) {
				
					_self._startSlideshow();
				
				}
			
			}, this.options.slideshow_interval);
		
		},
		// shows the clicked thumb's slide
		_slideTo			: function( pos ) {
			
			// return if clicking the same element or if currently animating
			if( pos === this.current || this.isAnimating )
				return false;
			
			this.isAnimating	= true;

			var $currentSlide	= this.$imgItems.eq( this.current ),
				$nextSlide		= this.$imgItems.eq( pos ),
				_self			= this,
				
				preCSS			= {zIndex	: 10},
				animCSS			= {opacity	: 1};

			// new slide will slide in from left or right side
            /*
			if( this.options.animation === 'sides' ) {
				preCSS.left		= ( pos > this.current ) ? -1 * this.elWidth : this.elWidth;
				animCSS.left	= 0;
			}  */
			// titles animation
			$nextSlide.find('div.ei-title > h2')
					  .css( 'margin-right', 100 + 'px' )
					  .stop()
					  .delay( this.options.speed * this.options.titlesFactor )
					  .animate({ marginRight : 0 + 'px', opacity : 1 }, this.options.titlespeed, this.options.titleeasing )
					  .end()
					  .find('div.ei-title > h3')
					  .css( 'margin-right', -100 + 'px' )
					  .stop()
					  .delay( this.options.speed * this.options.titlesFactor )
					  .animate({ marginRight : 0 + 'px', opacity : 1 }, this.options.titlespeed, this.options.titleeasing )
			$.when(
				// fade out current titles
				$currentSlide.css( 'z-index' , 1 ).find('div.ei-title > *').stop().fadeOut( this.options.speed / 2, function() {
					// reset style
					$(this).show().css( 'opacity', 0 );	
				}),
				// animate next slide in
				$nextSlide.css( preCSS ).stop().animate( animCSS, this.options.speed, this.options.easing ),
				// "sliding div" moves to new position
                this.$thumbs.removeClass('active_thumbs').eq(pos).addClass('active_thumbs')

                /*
				this.$sliderElem.stop().animate({
					left	: this.$thumbs.eq( pos ).position().left
				}, this.options.speed )*/
			).done( function() {
				// reset values
				$currentSlide.css( 'opacity' , 0 ).find('div.ei-title > *').css( 'opacity', 0 );
					_self.current	= pos;
					_self.isAnimating		= false;
				});
		},
		_initEvents			: function() {
			
			var _self	= this;
			
			// window resize
			$(window).on( 'smartresize.eislideshow', function( event ) {
				
				// resize the images
				_self._setImagesSize();
			
				// reset position of thumbs sliding div
				/*_self.$sliderElem.css( 'left', _self.$thumbs.eq( _self.current ).position().left );*/
			
			});
			// click the thumbs
			this.$thumbs.on( 'click.eislideshow', function( event ) {

				if( _self.options.autoplay ) {
					clearTimeout( _self.slideshow );
					_self.options.autoplay	= false;
				}
				var $thumb	= $(this),
					idx		= $thumb.index(); // exclude sliding div

				_self._slideTo( idx );
				return false;
			});
		}
	};
	var logError 				= function( message ) {
		if ( this.console ) {
			console.error( message );
		}
	};
	
	$.fn.eislideshow = function( options ) {
		if ( typeof options === 'string' ) {
			var args = Array.prototype.slice.call( arguments, 1 );
			this.each(function() {
				var instance = $.data( this, 'eislideshow' );
				if ( !instance ) {
					logError( "cannot call methods on eislideshow prior to initialization; " +
					"attempted to call method '" + options + "'" );
					return;
				}
				if ( !$.isFunction( instance[options] ) || options.charAt(0) === "_" ) {
					logError( "no such method '" + options + "' for eislideshow instance" );
					return;
				}
				instance[ options ].apply( instance, args );
			});
		} else {
			this.each(function() {
                var instance = $.data( this, 'eislideshow' );
				if ( !instance ) {
					$.data( this, 'eislideshow', new $.Slideshow( options, this ) );
				}
			});
		}
		return this;
	};
})( window, jQuery );